package traffic_restriction

import (
	"bytes"
	"crypto/sha256"
	"encoding/gob"
	"encoding/hex"
	"strings"
	"sync"
)

//网关限流配置，初步设计为：
//根据某一个字段，设定某一段时间内，最多xx次访问，xx=-1时表示不限流
type TrafficRestrictionConfig struct {
	LimitSet []LimitConfig
}

type LimitConfig struct {
	LimitAttrName *nameAndOr
	DurationTime  int64
	MaxAccessTime int64
}

type nameAndOr struct {
	//true=and;false=or
	types bool
	key   string
	sons  []*nameAndOr
}

func (n *nameAndOr) calValue(value map[string]interface{}) string {
	if n.key != "" {
		return str2Hash(intf2Hex(value[n.key]))
	}
	ss := make([]string, len(n.sons))
	for i, o := range n.sons {
		ss[i] = o.calValue(value)
	}
	comb := ")or("
	if n.types {
		comb = ")and("
	}
	return str2Hash("(" + strings.Join(ss, comb) + ")")
}

func intf2Hex(key interface{}) string {
	var buf bytes.Buffer
	enc := gob.NewEncoder(&buf)
	err := enc.Encode(key)
	if err != nil {
		return ""
	}
	return hex.EncodeToString(buf.Bytes())
}

func str2Hash(s string) string {
	b := sha256.Sum256([]byte(s))
	return hex.EncodeToString(b[:])
}

type TrafficRestrictionHandler interface {
	Do(string, LimitConfig) bool
}

var handlers = make(map[string]TrafficRestrictionHandler)
var handlerLock sync.RWMutex

func RegistTRHandler(types string, handler TrafficRestrictionHandler) {
	handlerLock.Lock()
	handlers[types] = handler
	handlerLock.Unlock()
}

func GetTRHandler(types string) TrafficRestrictionHandler {
	handlerLock.RLock()
	defer handlerLock.RUnlock()
	return handlers[types]
}
